package io.gitee.wl4837.alatool.core.response;

import cn.hutool.crypto.digest.MD5;
import io.gitee.wl4837.alatool.core.lang.HttpStatusCode;

import java.awt.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * 响应信息主体
 *
 * @author wangliang
 */
public class R<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 状态
     */
    private Integer code;

    /**
     * 描述状态
     */
    private String name;

    /**
     * 状态描述
     */
    private String message;

    /**
     * 状态描述
     */
    private String msg;

    /**
     * 时间戳
     */
    private Long timestamp;

    /**
     * 哈希值
     */
    private String hash = MD5.create().digestHex16("1");

    /**
     * 版本
     */
    private String version = "latest";

    /**
     * 接口
     */
    private String api;

    /**
     * 数据类型
     */
    private String type;

    /**
     * 元数据
     */
    private HashMap<String, Object> metadata = new HashMap<>();

    /**
     * 成功
     */
    private Integer isSuccess;

    /**
     * 成功
     */
    private Boolean success;

    /**
     * 日志编号
     */
    private String logId;

    /**
     * 布局
     */
    private ArrayList<Object> layout = new ArrayList<>();

    /**
     * 接收的ip
     */
    private String ip;

    /**
     * 调试
     */
    private Boolean debug = false;

    /**
     * 返回数据
     */
    private T data;

    /**
     * 语言
     */
    private String lang = "zh-cn";

    public R() {

    }

    public R(T data) {
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
        this.message = msg;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
        this.msg = message;
    }

    public Long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(Long timestamp) {
        this.timestamp = timestamp;
    }

    public String getHash() {
        return hash;
    }

    public void setHash(String hash) {
        this.hash = hash;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getApi() {
        return api;
    }

    public void setApi(String api) {
        this.api = api;
    }

    public boolean isDebug() {
        return debug;
    }

    public void setDebug(boolean debug) {
        this.debug = debug;
    }

    public HashMap<String, Object> getMetadata() {
        return metadata;
    }

    public void setMetadata(HashMap<String, Object> metadata) {
        this.metadata = metadata;
    }

    public Integer getIsSuccess() {
        return isSuccess;
    }

    public void setIsSuccess(Integer isSuccess) {
        this.isSuccess = isSuccess;
        this.success = isSuccess == 1;
    }

    public Boolean getSuccess() {
        return success;
    }

    public void setSuccess(Boolean success) {
        this.success = success;
        this.isSuccess = success ? 1 : 0;
    }

    public String getLogId() {
        return logId;
    }

    public void setLogId(String logId) {
        this.logId = logId;
    }

    public ArrayList<Object> getLayout() {
        return layout;
    }

    public void setLayout(ArrayList<Object> layout) {
        this.layout = layout;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getLang() {
        return lang;
    }

    public void setLang(String lang) {
        this.lang = lang;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public R<T> debug(Boolean debug) {
        this.setDebug(debug);
        return this;
    }

    public R<T> isSuccess(Integer isSuccess) {
        this.setIsSuccess(isSuccess);
        return this;
    }

    public R<T> success(Boolean success) {
        this.setSuccess(success);
        return this;
    }

    public R<T> logId(String logId) {
        this.setLogId(logId);
        return this;
    }

    public R<T> lang(String lang) {
        this.setLang(lang);
        return this;
    }

    public R<T> code(Integer code) {
        this.setCode(code);
        return this;
    }

    public R<T> name(String name) {
        this.setName(name);
        return this;
    }

    public R<T> message(String message) {
        this.setMessage(message);
        return this;
    }

    public R<T> msg(String msg) {
        this.setMsg(msg);
        return this;
    }

    public R<T> timestamp(Long timestamp) {
        this.setTimestamp(timestamp);
        return this;
    }

    public R<T> hash(String hash) {
        this.setHash(hash);
        return this;
    }

    public R<T> version(String version) {
        this.setVersion(version);
        return this;
    }

    public R<T> api(String api) {
        this.setApi(api);
        return this;
    }

    public R<T> type(String type) {
        this.setType(type);
        return this;
    }

    public R<T> ip(String ip) {
        this.setIp(ip);
        return this;
    }

    public R<T> data(T data) {
        this.setData(data);
        return this;
    }

    public R<T> layout(ArrayList<Object> layout) {
        this.setLayout(layout);
        return this;
    }

    public R<T> metadata(HashMap<String, Object> metadata) {
        this.setMetadata(metadata);
        return this;
    }

    public static <T> R<Void> ok() {
        return success();
    }

    public static <T> R<T> ok(T data) {
        return success(data);
    }

    public static <T> R<T> ok(T data, String message) {
        return success(data, message);
    }

    public static <T> R<T> ok(T data, String message, Integer code) {
        return success(data, message, code);
    }

    public static R<Void> suc() {
        return success();
    }

    public static <T> R<T> suc(T data) {
        return success(data);
    }

    public static <T> R<T> suc(T data, String message) {
        return success(data, message);
    }

    public static <T> R<T> suc(T data, String message, Integer code) {
        return success(data, message, code);
    }

    public static R<Void> success() {
        R<Void> r = new R<>();
        r.setCode(HttpStatusCode.OK.getCode());
        r.setMessage(HttpStatusCode.OK.getDescription());
        r.setName(HttpStatusCode.OK.getName());
        r.setTimestamp(System.currentTimeMillis());
        r.setSuccess(true);
        return r;
    }

    public static <T> R<T> success(T data) {
        R<T> r = new R<>();
        r.setCode(HttpStatusCode.OK.getCode());
        r.setMessage(HttpStatusCode.OK.getDescription());
        r.setName(HttpStatusCode.OK.getName());
        r.setTimestamp(System.currentTimeMillis());
        r.setSuccess(true);
        r.setData(data);
        return r;
    }

    public static <T> R<T> success(T data, String message) {
        R<T> r = new R<>();
        r.setCode(HttpStatusCode.OK.getCode());
        r.setName(HttpStatusCode.OK.getName());
        r.setTimestamp(System.currentTimeMillis());
        r.setMessage(message);
        r.setSuccess(true);
        r.setData(data);
        return r;
    }

    public static <T> R<T> success(T data, String message, Integer code) {
        R<T> r = new R<>();
        r.setName(HttpStatusCode.OK.getName());
        r.setTimestamp(System.currentTimeMillis());
        r.setCode(code);
        r.setMessage(message);
        r.setSuccess(true);
        r.setData(data);
        return r;
    }

    public static <T> R<T> success(T data, String message, Integer code, String name) {
        R<T> r = new R<>();
        r.setTimestamp(System.currentTimeMillis());
        r.setCode(code);
        r.setMessage(message);
        r.setSuccess(true);
        r.setData(data);
        r.setName(name);
        return r;
    }

    public static R<Void> fail() {
        return error();
    }

    public static <T> R<T> fail(T data) {
        return error(data);
    }

    public static <T> R<T> fail(T data, String message) {
        return error(data, message);
    }

    public static <T> R<T> fail(T data, String message, Integer code) {
        return error(data, message, code);
    }

    public static <T> R<Void> err() {
        return error();
    }

    public static <T> R<T> err(T data) {
        return error(data);
    }

    public static <T> R<T> err(T data, String message) {
        return error(data, message);
    }

    public static <T> R<T> err(T data, String message, Integer code) {
        return error(data, message, code);
    }

    public static R<Void> error() {
        R<Void> r = new R<>();
        r.setCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode());
        r.setMessage(HttpStatusCode.INTERNAL_SERVER_ERROR.getDescription());
        r.setName(HttpStatusCode.INTERNAL_SERVER_ERROR.getName());
        r.setTimestamp(System.currentTimeMillis());
        r.setSuccess(false);
        return r;
    }

    public static <T> R<T> error(T data) {
        R<T> r = new R<>();
        r.setCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode());
        r.setMessage(HttpStatusCode.INTERNAL_SERVER_ERROR.getDescription());
        r.setName(HttpStatusCode.INTERNAL_SERVER_ERROR.getName());
        r.setTimestamp(System.currentTimeMillis());
        r.setData(data);
        r.setSuccess(false);
        return r;
    }

    public static <T> R<T> error(T data, String message) {
        R<T> r = new R<>();
        r.setCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode());
        r.setName(HttpStatusCode.INTERNAL_SERVER_ERROR.getName());
        r.setTimestamp(System.currentTimeMillis());
        r.setMessage(message);
        r.setData(data);
        r.setSuccess(false);
        return r;
    }

    public static <T> R<T> error(T data, String message, Integer code) {
        R<T> r = new R<>();
        r.setName(HttpStatusCode.INTERNAL_SERVER_ERROR.getName());
        r.setTimestamp(System.currentTimeMillis());
        r.setCode(code);
        r.setMessage(message);
        r.setData(data);
        r.setSuccess(false);
        return r;
    }

    public static <T> R<T> error(T data, String message, Integer code, String name) {
        R<T> r = new R<>();
        r.setTimestamp(System.currentTimeMillis());
        r.setCode(code);
        r.setMessage(message);
        r.setData(data);
        r.setName(name);
        r.setSuccess(false);
        return r;
    }

    public static <T> R<T> other(T data, String message, Integer code) {
        R<T> r = new R<>();
        r.setTimestamp(System.currentTimeMillis());
        r.setCode(code);
        r.setMessage(message);
        r.setData(data);
        return r;
    }

    public static <T> R<T> other(T data, String message, Integer code, String name) {
        R<T> r = new R<>();
        r.setTimestamp(System.currentTimeMillis());
        r.setCode(code);
        r.setMessage(message);
        r.setData(data);
        r.setName(name);
        return r;
    }

    public static R<Void> unfound() {
        R<Void> r = new R<>();
        r.setTimestamp(System.currentTimeMillis());
        r.setCode(HttpStatusCode.NOT_FOUND.getCode());
        r.setMessage(HttpStatusCode.NOT_FOUND.getDescription());
        r.setName(HttpStatusCode.NOT_FOUND.getName());
        return r;
    }

    public static R<Void> found() {
        R<Void> r = new R<>();
        r.setTimestamp(System.currentTimeMillis());
        r.setCode(HttpStatusCode.FOUND.getCode());
        r.setMessage(HttpStatusCode.FOUND.getDescription());
        r.setName(HttpStatusCode.FOUND.getName());
        return r;
    }

    public static R<Void> syserror() {
        R<Void> r = new R<>();
        r.setTimestamp(System.currentTimeMillis());
        r.setCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode());
        r.setMessage(HttpStatusCode.INTERNAL_SERVER_ERROR.getDescription());
        r.setName(HttpStatusCode.INTERNAL_SERVER_ERROR.getName());
        return r;
    }

    @Override
    public String toString() {
        return super.toString();
    }

}
